package main

import (
	//goflag "flag"
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"

	flag "github.com/spf13/pflag"
)

//FlagStruct is struct for args
type FlagStruct struct {
	startpage  int
	endpage    int
	linenum    int
	asciistyle bool
	des        string
	inputfile  string
	reader     *bufio.Reader
}

func (f *FlagStruct) print() {
	fmt.Println("Args:")
	fmt.Println("startpage:", (f.startpage))
	fmt.Println("endpage:", (f.endpage))
	fmt.Println("linenum:", (f.linenum))
	fmt.Println("asciistyle:", (f.asciistyle))
	fmt.Println("des:", (f.des))
	fmt.Println("inputfile:", (f.inputfile))
}

var args FlagStruct

//Init is to get args and check whether they are correct
func Init() {
	flag.IntVarP(&args.startpage, "startpage", "s", -1, "Please input startpage")
	flag.IntVarP(&args.endpage, "endpage", "e", -1, "Please input endpage")
	flag.IntVarP(&args.linenum, "linenum", "l", 72, "Please input linenum")
	flag.BoolVarP(&args.asciistyle, "format", "f", false, "If asciistyle, set this to true")
	flag.StringVarP(&args.des, "destination", "d", "", "Please input destination")
	flag.Parse()
	args.startpage--
	args.endpage--
	if len(flag.Args()) > 0 {
		r, _ := regexp.Compile(`[^<>/\\\|:""\*\?]+\.\w+$`)
		if r.MatchString(flag.Args()[0]) {
			args.inputfile = flag.Args()[0]
		} else {
			args.inputfile = ""
		}

	} else {
		args.inputfile = ""
	}

	switch {
	case (args.startpage) < 0:
		fallthrough
	case (args.endpage) < 0:
		fallthrough
	case (args.startpage) > (args.endpage):
		panic("Wrong Startpage or Endpage")
	}

}

//FileAccessReadf is helper of FileAccess
func FileAccessReadf() {
	cmd := exec.Command("lp", "-d"+args.des)
	cmd.Stderr = os.Stderr
	for i := 0; i < args.startpage; i++ {
		_, err := args.reader.ReadString('\f')
		if err == io.EOF {
			panic("Over pages")
		}
	}
	for i := args.startpage; i <= args.endpage; i++ {
		str, err := args.reader.ReadString('\f')
		if err == io.EOF {
			break
		}
		if err != nil {
			panic("Cant Read content")
		}

		if args.des == "" {
			os.Stdout.WriteString(str)
		} else {
			cmd.Stdin = strings.NewReader(str)
			errr := cmd.Run()
			if errr != nil {
				panic("Cant print content")
			}
		}

	}

}

//FileAccessReadL is helper of FileAccess
func FileAccessReadL() {
	cmd := exec.Command("lp", "-d"+args.des)
	cmd.Stderr = os.Stderr
	//skip the pages before startpage
	for i := 0; i < args.startpage; i++ {
		for j := 0; j < args.linenum; j++ {
			_, err := args.reader.ReadString('\n')
			if err == io.EOF {
				panic("Over Pages")
			}

		}
	}

	for i := args.startpage; i <= args.endpage; i++ {
		for j := 0; j < args.linenum; j++ {
			str, err := args.reader.ReadString('\n')
			if err == io.EOF {
				break
			}
			if err != nil {
				panic("Cant Read content")
			}

			if args.des == "" {
				os.Stdout.WriteString(str)
			} else {
				cmd.Stdin = strings.NewReader(str)
				errr := cmd.Run()
				if errr != nil {
					panic("Cant print content")
				}
			}
		}
	}
}

//FileAccess is to access the io
func FileAccess() {
	var file *os.File
	if args.inputfile != "" {
		file, err := os.Open(args.inputfile)
		if err != nil {
			panic("Wrong filename")
		}
		args.reader = bufio.NewReader(file)
	} else {
		args.reader = bufio.NewReader(os.Stdin)
	}

	if args.asciistyle {
		FileAccessReadf()
	} else {
		FileAccessReadL()
	}
	file.Close()
}

func debugInit() {
	args.startpage = 1
	args.endpage = 1
	args.linenum = 10
	args.inputfile = "test.txt"
}

//Selpg is the main process
func Selpg() {
	Init()
	FileAccess()
}

func main() {
	Selpg()
}
